<?php


namespace App\Services;

use Elasticsearch\ClientBuilder;

class ElasticSearch
{
    //定义私有的静态属性
    private static $instance;
    public $client;
    //构造函数和克隆函数都声明为私有的
    private function __construct()
    {
        $this->client = ClientBuilder::create()->setHosts(['47.94.2.115:9200'])->build();
    }
    //私有的克隆方法，防止外部克隆
    private function __clone()
    {

    }
    //访问实例的公共静态方法（单例模式）
    public static function getInstance()
    {
        if (!(self::$instance instanceof self)){
            return self::$instance = new self();
        }else{
            return self::$instance;
        }
    }
    //创建并添加索引
    public function create($index,$id,$body,$field){
        $index = [
            'index'=>$index
        ];
        $isIndexs = $this->client->indices()->exists($index);

        //如果索引存在则创建
        if ($isIndexs){
            $param = [
                'index'=>$index,
                'type'=>'_doc',
                'id'=>$id,
                'body'=>$body
            ];
            return $this->client->create($param);
        }else{
            $params = [
                //索引的名称
                'index' => $index,
                'body' => [
                    //静态设置：只能在索引创建时或者在状态为 closed index（闭合的索引）上设置
                    'settings' => [
                        'number_of_shards' => 1, //主分片数，默认为5.只能在创建索引时设置，不能修改
                        'number_of_replicas' => 1,//每个主分片的副本数。默认为 1。
                        'analysis' => [//文本分析
                            //定制化分析器
                            'analyzer' => [
                                //指定是中文ik拼音分词
                                'chinese_ik_pinyin' => [
                                    // custom代表自定义的分词器。默认为stardard
                                    'type' => 'custom',
                                    //大小
                                    'tokenizer' => 'ik_max_word',
                                    //过滤器
                                    'filter' => 'my_pinyin'
                                ]
                            ],
                            'filter' => [//定义分词规则
                                'my_pinyin' => [
                                    'type' => 'pinyin',
                                    //这个会将第一个字母一个个分开.例如:刘德华->l,d,h.默认为:flase.如果开启,可能导致查询结果太过于模糊,准确率太低.
                                    'keep_separate_first_letter' => false,
                                    //如果打开,它将保存词的全拼,并按字分开保存.例如:刘德华> [liu,de,hua],默认为:true
                                    'keep_full_pinyin' => true,
                                    //是否保持原词.默认为:false
                                    'keep_original' => false,
                                    //设置最大keep_first_letter结果的长度,默认为:16
                                    'limit_first_letter_length' => 10,
                                    //小写非中文字母
                                    'lowercase' => true,
                                    //保存索引时删除重复的词语.例如: de的>de, 默认为: false, 注意:开启可能会影响位置相关的查询.
                                    'remove_duplicated_term' => true
                                ]
                            ],
                        ]
                    ],
                    'mappings' => [
                        '_source' => [
                            'enabled' => true
                        ],
                        'properties' => [
                            //指定给哪个字段加索引
                            "$field"=>[
                                'type'=>'text',
                                'analyzer' => 'chinese_ik_pinyin',
                                'search_analyzer' => 'chinese_ik_pinyin'
                            ]
                        ]
                    ]
                ]
            ];
            $response = $this->client->indices()->create($params);
            if ($response){
                $param = [
                    'index'=>$index,
                    'type'=>'_doc',
                    'id'=>$id,
                    'body'=>$body
                ];

                return $this->client->create($param);
            }
            return [
                'code'=>500,
                'msg'=>'error'
            ];
        }
    }
    //搜索
    public function searchIndex($index,$search,$type,$field){
        $param = [
            'index'=>$index,
            'type'=>$type,
            'body'=>[
                "query"=>[
                    "match"=> [
                        "$field"=> $search
                    ],
                ],
                "highlight"=>[
                    "fields"=>[
                        "$field"=>[
                            "pre_tags"=>["<span style='color:green'>"],
                            "post_tags"=>["</span>"]
                        ]
                    ]
                ]
            ]
        ];
        return $this->client->search($param);
    }
    //删除
    public function deleteIndex($index, $id)
    {

        $params = [
            'index' => $index,
            'type' => '_doc',
            'id' => $id
        ];
        return $this->client->delete($params);

    }

    //更新索引
    public function updateIndex($index, $id, $content)
    {
        $params = [
            'index' => $index,
            'type' => '_doc',
            'id' => $id,
            'body' => [
                'doc' => $content
            ]
        ];

        return $this->client->update($params);
    }
}

